package com.lihepeng.leecode.thread;

import java.util.concurrent.CountDownLatch;

/**
 * 打印0和奇偶数
 * 假设有这么一个类：
 * <p>
 * class ZeroEvenOdd {
 *   public ZeroEvenOdd(int n) { ... }      // 构造函数
 * public void zero(printNumber) { ... }  // 仅打印出 0
 * public void even(printNumber) { ... }  // 仅打印出 偶数
 * public void odd(printNumber) { ... }   // 仅打印出 奇数
 * }
 * 相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程：
 * <p>
 * 线程 A 将调用 zero()，它只输出 0 。
 * 线程 B 将调用 even()，它只输出偶数。
 * 线程 C 将调用 odd()，它只输出奇数。
 * 每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ，其中序列的长度必须为 2n。
 * <p>
 *  
 * <p>
 * 示例 1：
 * <p>
 * 输入：n = 2
 * 输出："0102"
 * 说明：三条线程异步执行，其中一个调用 zero()，另一个线程调用 even()，最后一个线程调用odd()。正确的输出为 "0102"。
 * 示例 2：
 * <p>
 * 输入：n = 5
 * 输出："0102030405"
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/print-zero-even-odd
 *
 * @author eloancn
 */
public class Solution1116 {
    public static void main(String[] args) throws InterruptedException {
        Wrapper wrapper = new Wrapper(2);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        CountDownLatch countDownLatch1 = new CountDownLatch(1);
        CountDownLatch countDownLatch2 = new CountDownLatch(1);
        new Thread(new PrintZero(countDownLatch)).start();
        countDownLatch.await();
        new Thread(new PrintJiShu(wrapper, countDownLatch1), "技术线程").start();
        countDownLatch1.await();
        new Thread(new PrintOuShu(wrapper, countDownLatch2), "偶数线程").start();
        countDownLatch2.await();

    }

}

class PrintZero implements Runnable {
    private CountDownLatch countDownLatch;

    @Override
    public void run() {
        System.out.print("0");
        countDownLatch.countDown();
    }

    public PrintZero(CountDownLatch countDownLatch) {
        super();
        this.countDownLatch = countDownLatch;
    }

}

class PrintJiShu implements Runnable {
    private volatile Wrapper wrapper;
    private CountDownLatch countDownLatch;

    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (wrapper.getCount() % 2 != 0) {
            System.out.print(Thread.currentThread().getName() + wrapper.getCount());
        } else {
            wrapper.setCount(wrapper.getCount() + 1);
            System.out.print(Thread.currentThread().getName() + wrapper.getCount());
        }
        countDownLatch.countDown();
    }

    public PrintJiShu(Wrapper wrapper, CountDownLatch countDownLatch) {
        super();
        this.wrapper = wrapper;
        this.countDownLatch = countDownLatch;
    }

    public Wrapper getWrapper() {
        return wrapper;
    }

    public void setWrapper(Wrapper wrapper) {
        this.wrapper = wrapper;
    }

    public CountDownLatch getCountDownLatch() {
        return countDownLatch;
    }

    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }


}

class PrintOuShu implements Runnable {
    private volatile Wrapper wrapper;
    private CountDownLatch countDownLatch;

    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (wrapper.getCount() % 2 == 0) {
            System.out.print(Thread.currentThread().getName() + wrapper.getCount());
        } else {
            wrapper.setCount(wrapper.getCount() + 1);
            System.out.print(Thread.currentThread().getName() + wrapper.getCount());
        }
        countDownLatch.countDown();
    }

    public Wrapper getWrapper() {
        return wrapper;
    }

    public void setWrapper(Wrapper wrapper) {
        this.wrapper = wrapper;
    }

    public CountDownLatch getCountDownLatch() {
        return countDownLatch;
    }

    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public PrintOuShu(Wrapper wrapper, CountDownLatch countDownLatch) {
        super();
        this.wrapper = wrapper;
        this.countDownLatch = countDownLatch;
    }


}

class Wrapper {
    private Integer count;

    public Wrapper(Integer count) {
        super();
        this.count = count;
    }

    public Integer getCount() {
        return count;
    }

    public void setCount(Integer count) {
        this.count = count;
    }

}
